package com.xjy.common.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.xjy.common.util.PageBean;
@SuppressWarnings("unchecked")
public abstract class BaseDao<T, ID extends Serializable> extends HibernateDaoSupport{
	protected static final String SELECT = " select ";
	protected static final String FROM = " from ";
	protected static final String WHERE = " where ";
	
	protected static final String AND = " and ";
	protected static final String OR = " or ";
	
	protected static final String ORDERBY = " order by ";
	protected JdbcTemplate jdbcTemplate;
	protected Class<T> entityClass;
	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	public Class<T> getEntityClass() {
		ParameterizedType type = (ParameterizedType)getClass().getGenericSuperclass();
	    this.entityClass = ((Class)type.getActualTypeArguments()[0]);
		return entityClass;
	}
	/**
	 * 保存
	 * @param obj
	 */
	public void save(T obj) {
		getHibernateTemplate().save(obj);
	}
	/**
	 * 更新
	 * @param obj
	 */
	public void update(T obj){
	    getHibernateTemplate().update(obj);
	}
	public void saveOrUpdate(T obj){
		getHibernateTemplate().saveOrUpdate(obj);
	}
	/**
	 * 通过 ID删除实体
	 * @param id
	 */
	public void delById(ID id) {
		getHibernateTemplate().delete(getHibernateTemplate().get(getEntityClass(), id));
	}
	/**
	 * 通过对象删除实体
	 * @param obj
	 */
	public void delete(T obj) {
	    getHibernateTemplate().delete(obj);
	}
	/**
	 * 通过ID集合批量删除
	 * @param ids
	 */
	public int bulkDelByIds(ID[] ids) {
		String queryString = "delete " +FROM+ getEntityClass().getName()
				+ " where id in (:ids) ";
		Query query = getSession().createQuery(queryString);
		query.setParameterList("ids", ids);
		return query.executeUpdate();
	}
	/**
	 * 根据条件判断某实体是否存在 
	 * @param condition
	 * @param parameters
	 * @return
	 */
	public boolean exists(String condition, Object[] parameters){
	    return findTotalCount(condition, parameters) != 0;
	}
	/**
	 * 通过ID查找实体
	 * @param id
	 * @return
	 */
	public T get(ID id) {
		return getHibernateTemplate().get(getEntityClass(), id);
	}
	/**
	 * 通过ID加载实体
	 * @param id
	 * @return
	 */
	public T load(ID id) {
		return getHibernateTemplate().load(getEntityClass(), id);
	}
	/**
	 * 单实体查找
	 * @param condition
	 * @param parameters
	 * @return
	 */
	public T findUnique(String condition, Object[] parameters) {
		String hql = FROM + getEntityClass().getName();
		if (condition.length() != 0)
			hql = hql + WHERE + condition;
		Query query = createQuery(getSession(),condition,parameters);
		query.setFirstResult(0);
        query.setMaxResults(1);
		List list = query.list();
		if(null!=list&&list.size()>1){//?
			return (T)list.get(0);
		}
		return null;
	}
	/**
	 * 多实体查找
	 * @param condition
	 * @param parameters
	 * @param sort
	 * @return
	 */
	public List<T> find(String condition, Object[] parameters, String sort){
	    String hql = FROM + getEntityClass().getName();
	    if (condition != null && !condition.trim().equals("")) {
	      hql = hql + WHERE + condition;
	    }
	    if (sort != null && !sort.equals("")) {
	      String tmpHql = hql.toLowerCase();
	      if (tmpHql.indexOf(" order by ") < 0)
	        hql = hql + " order by " + sort;
	    }
	    return getHibernateTemplate().find(hql, parameters);
	}
	/**
	 * 查找所有实体
	 * @return
	 */
	public List<T> findAll() {
		return find(null, null, null);
	}
	/**
	 * 获取总数
	 * @param condition
	 * @param parameters
	 * @return
	 */
	public int findTotalCount( String condition,  Object[] parameters) {
		String hql = " select count(*) from "
				+ getEntityClass().getName();
		if ((condition != null) && (!condition.trim().equals(""))) {
			hql = hql + " where " + condition;
		}
		Query query = createQuery(getSession(), hql, parameters);
		Object obj= query.uniqueResult();
		if (obj == null) {
			return 0;
		}
		return Integer.valueOf(obj.toString());
	}
	/**
	 * 分页查找,返回当前查找页数据
	 * @param condition
	 * @param parameters
	 * @param sort
	 * @param page：当前第几页
	 * @param limit：页大小
	 * @return
	 */
	private List<T> findWithPaging(String condition, Object[] parameters,
			String sort, int page, int limit) {
		String hql = FROM + getEntityClass().getName();
		if (condition != null && !condition.trim().equals("")) {
			hql = hql + WHERE + condition;
		}
		if (sort != null && !sort.equals("")) {
			String tmpHql = hql.toLowerCase();
			if (tmpHql.indexOf(" order by ") < 0)
				hql = hql + " order by " + sort;
		}
		
		Query query = createQuery(getSession(), hql, parameters);
		query.setFirstResult(page <= 0 ? 0 : limit * (page - 1));
		query.setMaxResults(limit);
		return query.list();
	}
	/**
	 * 分页功能，返回封装的分页BEAN
	 * @param condition：条件
	 * @param parameters：参数
	 * @param sort：排序
	 * @param page：当前第几页
	 * @param limit：分页大小
	 * @return
	 */
	public PageBean getPageBean(String condition, Object[] parameters,
			String sort, int page, int limit){
		int allRows=this.findTotalCount(condition, parameters);
		return PageBean.packagePageBean(limit, page, findWithPaging(condition,parameters,sort,page,limit), allRows);
	}
	/**
	 * 创建QUERY接口
	 * @param session
	 * @param hql
	 * @param parameters
	 * @return
	 */
	public Query createQuery(Session session, String hql, Object[] parameters) {
		Query query = session.createQuery(hql);
		if (parameters != null) {
			for (int i = 0; i < parameters.length; i++) {
				if (parameters[i] != null) {
					query.setParameter(i, parameters[i]);
				}
			}
		}
		return query;
	}

	
	public List<T> findByHql(String hql) {
		return findByHql(hql, null);
	}
	
	public List<T> findByHql(final String hql, final Object[] objs) {
		return (List) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				System.out.println(hql);
				Query query = session.createQuery(hql);
				if (objs != null) {
					for (int i = 0; i < objs.length; ++i) {
						query.setParameter(i, objs[i]);
					}
				}
				return query.list();
			}
		});
	}
}
